package com.example.searcher.search;

import java.io.*;
import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Parser {
    private static final String FILE_PATH = "E:\\codeforbit\\project\\searchEngine\\docs_search_index\\jdk-8u451-docs-all\\docs\\api";

    private Index index = new Index();
    public void run() throws InterruptedException {

        long beg = System.currentTimeMillis();
        ArrayList<File> filesList = new ArrayList<File>();

        // 枚举出所有文件
        enumFile(FILE_PATH, filesList);
        // 针对每个文件进行提取索引
        // 由于这里的for循环遍历耗时过长，使用线程池
        ExecutorService executor = Executors.newFixedThreadPool(4);
        // 等待 fileList.size() 个线程都结束后才可进行主线程的下一步操作
        CountDownLatch latch = new CountDownLatch(filesList.size());

        for (File file : filesList) {
            executor.submit(()-> {
                System.out.println("开始检索：" + file.getName());
                parseHtml(file);
                latch.countDown();
            });
        }
        // 可能出现线程池未执行完就执行索引保存的操作，因为线程的调度 是随机的，所以这里添加上一个强制等待
        latch.await();
        // 线程池创建出的线程默认是前台线程，当线程将所有任务全部执行完后会进入等待任务的状态，这里要手动杀死所有线程来达到结束进程的效果
        executor.shutdown();
//        for(File file:filesList){
//            System.out.println(" 开始检索： "+file.getName());
//            parseHtml(file);
//        }
        // 将制作好的索引保存到硬盘目录中
        index.save();
        long end = System.currentTimeMillis();
        System.out.println("索引制作完成，花费时间：" + (end - beg));
    }

    private void enumFile(String filePath, ArrayList<File> filesList) {
        File file = new File(filePath);
        File[] files = file.listFiles();
        for (File f : files) {
            if(f.isDirectory()){
                enumFile(f.getAbsolutePath(), filesList);
            }
            else if(f.getAbsolutePath().endsWith(".html")){
                filesList.add(f);
            }
        }
    }

    private void parseHtml(File f) {
        // 获取标题
        String title = parseTitle(f);
        // 获取要跳转的URL
        String url = parseUrl(f);
        // 获取文档的内容
        String content = parseContentByRegex(f);
        // 对每个解析出来的文件进行创建索引
        index.addDoc(title, url, content);
//        String s = title + "\n" + url + "\n" + content;
//        System.out.println(s);
    }

    public String parseContent(File f) {
        //获取文章正文
        try{
            FileReader fileReader = new FileReader(f);
            boolean isContent = true;
            StringBuffer content = new StringBuffer();
            while(true){
                int ret = fileReader.read();
                if(ret == -1){
                    break;
                }
                char c = (char)ret;
                if(isContent) {
                    if (c == '<') {
                        isContent = false;
                        continue;
                    }
                    if (c == '\r' || c == '\n') {
                        c = ' ';
                    }
                    content.append(c);
                } else {
                    if(c == '>'){
                        isContent = true;
                    }
                }
            }
            fileReader.close();
            return content.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private String readContent(File f) {
        StringBuffer content = new StringBuffer();
        try(BufferedReader bufferedReader = new BufferedReader(new FileReader(f))){
            // 去掉上面方法中的开关，将所有正文全部读入
            while(true){
                String line = bufferedReader.readLine();
                if(line == null){
                    break;
                }
                content.append(line);
            }
            return content.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
    public String parseContentByRegex(File f) {
        String content = readContent(f);
        // 使用正则表达式替换正文中的script标签
        content = content.replaceAll("<script.*?>(.*?)</script>", " ");
        // 替换正文中所有标签
        // 注意这两步不能写反，否则就会失去取出script标签的功能，和第一次写的方法功能相同了
        content = content.replaceAll("<.*?>"," ");

        content = content.replaceAll("\\s+", " ");
        return content;
    }
    private String parseUrl(File f) {
        // 采用拼接的方式实现获取官方文档的URL跳转
        String indexURL = "https://docs.oracle.com/javase/8/docs/api";
        String lastURL = f.getAbsolutePath().substring(FILE_PATH.length());
        return indexURL + lastURL;
    }

    private String parseTitle(File f) {
        // 直接获取文件名,返回结果是一个字符串，再将字符串进行截取获取没有后缀名的字符串
        return f.getName().substring(0, f.getName().length() - ".html".length());
    }

    public static void main(String[] args) throws InterruptedException {
        Parser p = new Parser();
        p.run();
    }
}
